//
//  SDTSRenderView.m
//  STDRenderSDK
//
//  Created by 陈学明 on 2023/3/16.
//

#import "STDSRenderView.h"
#import <OpenGLES/ES3/gl.h>
#import "STDSRenderThread.h"


@interface STDSRenderView ()
@property (nonatomic, strong) CAEAGLLayer *glLayer;
@property (nonatomic, strong) EAGLContext *context;
@property (nonatomic, strong, readwrite) STDSRenderer *renderer;

@property (nonatomic, assign) unsigned int myFrameBuffer;
@property (nonatomic, assign) unsigned int myRenderBuffer;
@property (nonatomic, strong) STDSRenderThread *renderThread;
@property (nonatomic, assign) BOOL isReady;
@property (nonatomic, assign) CGSize composeSize;
@end

@implementation STDSRenderView

- (instancetype)initWithFrame:(CGRect)frame composeSize:(CGSize)composeSize {
    self = [super initWithFrame:frame];
    if (self) {
        _composeSize = composeSize;
        _glLayer = [[CAEAGLLayer alloc] init];
        _glLayer.frame = [self canvas];
        _glLayer.contentsScale = [UIScreen mainScreen].scale;
        [self.layer addSublayer:_glLayer];
        _myFrameBuffer = 0;
        _myRenderBuffer = 0;
        _isReady = NO;
        _renderThread = [[STDSRenderThread alloc] init];
        [self createGL];
    }
    return self;
}

- (void)createGL {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        weakSelf.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
        [EAGLContext setCurrentContext:weakSelf.context];
        weakSelf.renderer = [[STDSRenderer alloc] init];
        [weakSelf setupBuffer];
        [weakSelf reViewPortSize];
        [weakSelf.delegate onReadyRenderView:weakSelf];
    }];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    _glLayer.frame = [self canvas];
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        [weakSelf reViewPortSize];
        [weakSelf.renderer renderPrograss:0.0];
        [weakSelf.context presentRenderbuffer:GL_RENDERBUFFER];
    }];
}

#pragma mark -GL相关
- (void)destoryRenderAndFrameBuffer {
    if (_myFrameBuffer > 0) {
        glDeleteFramebuffers(1, &_myFrameBuffer);
        _myFrameBuffer = 0;
    }
    
    if (_myRenderBuffer > 0) {
        glDeleteRenderbuffers(1, &_myRenderBuffer);
        _myRenderBuffer = 0;
    }
}

- (void)setupBuffer {
    glGenRenderbuffers(1, &_myRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _myRenderBuffer);
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_glLayer];
    
    glGenFramebuffers(1, &_myFrameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _myFrameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _myRenderBuffer);
}

- (void)reViewPortSize {
    glClearColor(0, 0.0, 0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    CGSize size = CGSizeMake(_glLayer.frame.size.width * _glLayer.contentsScale, _glLayer.frame.size.height * _glLayer.contentsScale);
    glViewport(0, 0, _glLayer.frame.size.width * _glLayer.contentsScale, _glLayer.frame.size.height * _glLayer.contentsScale);
    [_renderer setComposeSizeSRC:size];
}

- (CGRect)canvas {
    CGSize viewSize = self.frame.size;
    if(fabs(viewSize.width*viewSize.height) <= 0.001 || fabs(_composeSize.width*_composeSize.height) <= 0.001) {
        return CGRectZero;
    }
    float viewP = viewSize.height/viewSize.width;
    float composeP = _composeSize.height/_composeSize.width;
    CGRect canvaseRect;
    if (viewP > composeP) {
        canvaseRect.size.width = viewSize.width;
        canvaseRect.size.height = viewSize.width * composeP;
        canvaseRect.origin.x = 0;
        canvaseRect.origin.y = (viewSize.height - canvaseRect.size.height)/2.0;
    } else {
        canvaseRect.size.width = viewSize.height/composeP;
        canvaseRect.size.height = viewSize.height;
        canvaseRect.origin.x = (viewSize.width - canvaseRect.size.width)/2.00;
        canvaseRect.origin.y = 0;
    }
    return canvaseRect;
}

#pragma mark - 渲染引擎相关
- (void)renderPrograss:(CGFloat)prograss {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        glClearColor(0, 0.0, 0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
        [weakSelf.renderer renderPrograss:prograss];
        [weakSelf.context presentRenderbuffer:GL_RENDERBUFFER];
    }];
}

- (void)render {
    glClearColor(0, 0.0, 0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    [self.renderer renderPrograss:0.0];
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (STDSGLImageParam *)addImageLayerWithImagePath:(NSString *)imagePath {
    return [self.renderer addImageLayerWithImagePath: imagePath];
}

- (void)replaceLayerAssetImgPath:(NSString *)path {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        [weakSelf.renderer replaceLayerAssetImgPath:path];
    }];
}


- (void)replaceLayerAssetImgPath:(NSString *)path layerID:(int)layerID {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        [weakSelf.renderer selectLayer:layerID];
        [weakSelf.renderer replaceLayerAssetImgPath:path];
    }];
}

- (void)replaceLayerTextureID:(unsigned int)textureID width:(CGFloat)width height:(CGFloat)height {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        [weakSelf.renderer replaceLayerTextureID:textureID width:width height:height];
    }];
}

- (void)replaceLayerData:(unsigned char *)data width:(CGFloat)width height:(CGFloat)height {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        [weakSelf.renderer replaceLayerData:data width:width height:height];
    }];
}

- (void)onRendererThreadBlock:(void(^)(STDSRenderView *renderView))block {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        if (block) {
            block(weakSelf);
        }
    }];
}

- (CALayer *)glLayer {
    return _glLayer;
}

- (void)takeImageWithComplate:(void(^)(UIImage *image))complate {
    __weak STDSRenderView *weakSelf = self;
    [_renderThread addOperationWithBlock:^{
        int width = 0;
        int height = 0;
        unsigned char *data = NULL;
        [weakSelf.renderer readPixelOfPrograss:0.0 width:&width height:&height data:&data];
        if (data == NULL || width <= 0 || height <= 0) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (complate) {
                    complate(nil);
                }
            });
            return;
        }
        NSUInteger len = width * height * 4;
        CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, len, NULL);
        int bitsPerComponent = 8;
        int bitsPerPixel = 32;
        int bytesPerRow = 4 * width;
        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
        CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
        CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
        
        UIGraphicsBeginImageContext(CGSizeMake(width, height));
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        CGImageRelease(imageRef);
        CGDataProviderRelease(provider);
        CGColorSpaceRelease(colorSpaceRef);
        free(data);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (complate) {
                complate(image);
            }
        });
    }];
    
}

- (void)addEffectType:(STDSEffectType)effectType {
    [self.renderer addEffectType:effectType];
}

- (void)destroy {
    __weak STDSRenderView *weakSelf = self;
    [self.renderThread addOperationWithBlock:^{
        [weakSelf destoryRenderAndFrameBuffer];
        [weakSelf.renderer destroyRenderEngine];
    }];
    [self.renderThread close];
}

- (void)testGL {
    __weak STDSRenderView *weakSelf = self;
    [self.renderThread addOperationWithBlock:^{
        [weakSelf.renderer testGL];
    }];
}

- (void)dealloc {
//    [self destroy];
    NSLog(@"dealloc--SDTSRenderView");
}
@end
